package net.pugsplace.gpremacy.rules.loaders;

import java.io.File;

import net.pugsplace.gpremacy.rules.RuleConfiguration;
import net.pugsplace.gpremacy.rules.RuleProxy;
import net.pugsplace.gpremacy.rules.RuleSet;

import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

public class PythonRuleLoader implements RuleLoader {
	private static final String PYTHON_LOAD_CLASSNAME = "RuleSet";

	/**
	 * Create a RuleSet object from a Python script
	 * 
	 * @param path
	 *            The path of the lead Python script to interpret
	 * @param className
	 *            The main class name to load
	 * @throws RuntimeException
	 *             when the ruleset is not loaded correctly
	 * @return A non-null RuleSet object
	 */
	public static RuleSet loadPythonRuleset(String path, String className) {
		RuleProxy rp = new RuleProxy();
		PythonInterpreter interpreter = new PythonInterpreter();

		if (new File(path).canRead() == false) {
			throw new RuntimeException("Could not load class from file " + path);
		}

		try {
			interpreter.execfile(path);
		} catch (Exception e) {
			throw new RuntimeException("Could not compile class from file " + path, e);
		}

		PyObject cls = interpreter.get(className);

		if (cls == null) {
			throw new RuntimeException("Could not read class named " + className);
		}
		PyObject pyServlet = cls.__call__();
		if (pyServlet == null) {
			throw new RuntimeException("Could not instance class named " + className);
		}

		RuleConfiguration rc = (RuleConfiguration) pyServlet.__tojava__(RuleConfiguration.class);
		if (rc == null) {
			throw new RuntimeException("Could not cast class named " + className + " to RuleConfiguration");
		}

		try {
			rc.initialize(rp);
		} catch (Exception e) {
			throw new RuntimeException("Could not initialize ruleset from class named " + className);
		}

		if (rp.isValid() == false) {
			throw new RuntimeException("Ruleset failed to validate for class named " + className);
		}

		return rp.getRuleSet();
	}

	public boolean canLoad(String path) {
		// Determine extension
		int last = path.lastIndexOf('.');
		if (last < 0) {
			throw new IllegalArgumentException("Ruleset name does not have an extension; cannot determine type");
		}
		String extension = path.substring(last + 1);

		return extension.equalsIgnoreCase("py");
	}

	public RuleSet loadRuleset(String path) {
		return loadPythonRuleset(path, PYTHON_LOAD_CLASSNAME);
	}
}
